home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / cpu / t11 / t11.c next >
C/C++ Source or Header  |  1999-12-31  |  14KB  |  452 lines

  1. /*** t11: Portable DEC T-11 emulator ******************************************
  2.  
  3.     Copyright (C) Aaron Giles 1998
  4.  
  5.     System dependencies:    long must be at least 32 bits
  6.                             word must be 16 bit unsigned int
  7.                             byte must be 8 bit unsigned int
  8.                             long must be more than 16 bits
  9.                             arrays up to 65536 bytes must be supported
  10.                             machine must be twos complement
  11.  
  12. *****************************************************************************/
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include "cpuintrf.h"
  18. #include "mamedbg.h"
  19. #include "t11.h"
  20.  
  21.  
  22. static UINT8 t11_reg_layout[] = {
  23.     T11_PC, T11_SP, T11_PSW, T11_IRQ0_STATE, T11_IRQ1_STATE, T11_IRQ2_STATE, T11_IRQ3_STATE, -1,
  24.     T11_R0,T11_R1,T11_R2,T11_R3,T11_R4,T11_R5, -1,
  25.     T11_BANK0,T11_BANK1,T11_BANK2,T11_BANK3, T11_BANK4,T11_BANK5,T11_BANK6,T11_BANK7, 0
  26. };
  27.  
  28. static UINT8 t11_win_layout[] = {
  29.      0, 0,80, 4,    /* register window (top rows) */
  30.      0, 5,31,17,    /* disassembler window (left colums) */
  31.     32, 5,48, 8,    /* memory #1 window (right, upper middle) */
  32.     32,14,48, 8,    /* memory #2 window (right, lower middle) */
  33.      0,23,80, 1,    /* command line window (bottom rows) */
  34. };
  35.  
  36. /* T-11 Registers */
  37. typedef struct
  38. {
  39.     PAIR    ppc;    /* previous program counter */
  40.     PAIR    reg[8];
  41.     PAIR    psw;
  42.     UINT16  op;
  43.     UINT8    wait_state;
  44.     UINT8   *bank[8];
  45.     INT8    irq_state[4];
  46.     int        interrupt_cycles;
  47.     int     (*irq_callback)(int irqline);
  48. } t11_Regs;
  49.  
  50. static t11_Regs t11;
  51.  
  52. /* public globals */
  53. int    t11_ICount=50000;
  54.  
  55. /* register definitions and shortcuts */
  56. #define REGD(x) t11.reg[x].d
  57. #define REGW(x) t11.reg[x].w.l
  58. #define REGB(x) t11.reg[x].b.l
  59. #define SP REGW(6)
  60. #define PC REGW(7)
  61. #define SPD REGD(6)
  62. #define PCD REGD(7)
  63. #define PSW t11.psw.b.l
  64.  
  65. /* shortcuts for reading opcodes */
  66. INLINE int ROPCODE(void)
  67. {
  68.     int pc = PCD;
  69.     PC += 2;
  70.     return READ_WORD(&t11.bank[pc >> 13][pc & 0x1fff]);
  71. }
  72.  
  73. /* shortcuts for reading/writing memory bytes */
  74. #define RBYTE(addr)      T11_RDMEM(addr)
  75. #define WBYTE(addr,data) T11_WRMEM((addr), (data))
  76.  
  77. /* shortcuts for reading/writing memory words */
  78. INLINE int RWORD(int addr)
  79. {
  80.     return T11_RDMEM_WORD(addr & 0xfffe);
  81. }
  82.  
  83. INLINE void WWORD(int addr, int data)
  84. {
  85.     T11_WRMEM_WORD(addr & 0xfffe, data);
  86. }
  87.  
  88. /* pushes/pops a value from the stack */
  89. INLINE void PUSH(int val)
  90. {
  91.     SP -= 2;
  92.     WWORD(SPD, val);
  93. }
  94.  
  95. INLINE int POP(void)
  96. {
  97.     int result = RWORD(SPD);
  98.     SP += 2;
  99.     return result;
  100. }
  101.  
  102. /* flag definitions */
  103. #define CFLAG 1
  104. #define VFLAG 2
  105. #define ZFLAG 4
  106. #define NFLAG 8
  107.  
  108. /* extracts flags */
  109. #define GET_C (PSW & CFLAG)
  110. #define GET_V (PSW & VFLAG)
  111. #define GET_Z (PSW & ZFLAG)
  112. #define GET_N (PSW & NFLAG)
  113.  
  114. /* clears flags */
  115. #define CLR_C (PSW &= ~CFLAG)
  116. #define CLR_V (PSW &= ~VFLAG)
  117. #define CLR_Z (PSW &= ~ZFLAG)
  118. #define CLR_N (PSW &= ~NFLAG)
  119.  
  120. /* sets flags */
  121. #define SET_C (PSW |= CFLAG)
  122. #define SET_V (PSW |= VFLAG)
  123. #define SET_Z (PSW |= ZFLAG)
  124. #define SET_N (PSW |= NFLAG)
  125.  
  126. /****************************************************************************
  127.  * Checks active interrupts for a valid one
  128.  ****************************************************************************/
  129. static void t11_check_irqs(void)
  130. {
  131.     int priority = PSW & 0xe0;
  132.     int irq;
  133.  
  134.     /* loop over IRQs from highest to lowest */
  135.     for (irq = 0; irq < 4; irq++)
  136.     {
  137.         if (t11.irq_state[irq] != CLEAR_LINE)
  138.         {
  139.             /* get the priority of this interrupt */
  140.             int new_pc = RWORD(0x38 + (irq * 0x10));
  141.             int new_psw = RWORD(0x3a + (irq * 0x10));
  142.  
  143.             /* if it's greater than the current priority, take it */
  144.             if ((new_psw & 0xe0) > priority)
  145.             {
  146.                 if (t11.irq_callback)
  147.                     (*t11.irq_callback)(irq);
  148.  
  149.                 /* push the old state, set the new one */
  150.                 PUSH(PSW);
  151.                 PUSH(PC);
  152.                 PCD = new_pc;
  153.                 PSW = new_psw;
  154.                 priority = new_psw & 0xe0;
  155.  
  156.                 /* count 50 cycles (who knows what it really is) and clear the WAIT flag */
  157.                 t11.interrupt_cycles += 50;
  158.                 t11.wait_state = 0;
  159.             }
  160.         }
  161.     }
  162. }
  163.  
  164. /* includes the static function prototypes and the master opcode table */
  165. #include "t11table.c"
  166.  
  167. /* includes the actual opcode implementations */
  168. #include "t11ops.c"
  169.  
  170. /****************************************************************************
  171.  * Get all registers in given buffer
  172.  ****************************************************************************/
  173. unsigned t11_get_context(void *dst)
  174. {
  175.     if( dst )
  176.         *(t11_Regs*)dst = t11;
  177.     return sizeof(t11_Regs);
  178. }
  179.  
  180. /****************************************************************************
  181.  * Set all registers to given values
  182.  ****************************************************************************/
  183. void t11_set_context(void *src)
  184. {
  185.     if( src )
  186.         t11 = *(t11_Regs*)src;
  187.     t11_check_irqs();
  188. }
  189.  
  190. /****************************************************************************
  191.  * Return program counter
  192.  ****************************************************************************/
  193. unsigned t11_get_pc(void)
  194. {
  195.     return PCD;
  196. }
  197.  
  198. /****************************************************************************
  199.  * Set program counter
  200.  ****************************************************************************/
  201. void t11_set_pc(unsigned val)
  202. {
  203.     PC = val;
  204. }
  205.  
  206. /****************************************************************************
  207.  * Return stack pointer
  208.  ****************************************************************************/
  209. unsigned t11_get_sp(void)
  210. {
  211.     return SPD;
  212. }
  213.  
  214. /****************************************************************************
  215.  * Set stack pointer
  216.  ****************************************************************************/
  217. void t11_set_sp(unsigned val)
  218. {
  219.     SP = val;
  220. }
  221.  
  222. /****************************************************************************
  223.  * Return a specific register
  224.  ****************************************************************************/
  225. unsigned t11_get_reg(int regnum)
  226. {
  227.     switch( regnum )
  228.     {
  229.         case T11_PC: return PCD;
  230.         case T11_SP: return SPD;
  231.         case T11_PSW: return PSW;
  232.         case T11_R0: return REGD(0);
  233.         case T11_R1: return REGD(1);
  234.         case T11_R2: return REGD(2);
  235.         case T11_R3: return REGD(3);
  236.         case T11_R4: return REGD(4);
  237.         case T11_R5: return REGD(5);
  238.         case T11_IRQ0_STATE: return t11.irq_state[T11_IRQ0];
  239.         case T11_IRQ1_STATE: return t11.irq_state[T11_IRQ1];
  240.         case T11_IRQ2_STATE: return t11.irq_state[T11_IRQ2];
  241.         case T11_IRQ3_STATE: return t11.irq_state[T11_IRQ3];
  242.         case T11_BANK0: return (unsigned)(t11.bank[0] - OP_RAM);
  243.         case T11_BANK1: return (unsigned)(t11.bank[1] - OP_RAM);
  244.         case T11_BANK2: return (unsigned)(t11.bank[2] - OP_RAM);
  245.         case T11_BANK3: return (unsigned)(t11.bank[3] - OP_RAM);
  246.         case T11_BANK4: return (unsigned)(t11.bank[4] - OP_RAM);
  247.         case T11_BANK5: return (unsigned)(t11.bank[5] - OP_RAM);
  248.         case T11_BANK6: return (unsigned)(t11.bank[6] - OP_RAM);
  249.         case T11_BANK7: return (unsigned)(t11.bank[7] - OP_RAM);
  250.         case REG_PREVIOUSPC: return t11.ppc.w.l;
  251.         default:
  252.             if( regnum <= REG_SP_CONTENTS )
  253.             {
  254.                 unsigned offset = SPD + 2 * (REG_SP_CONTENTS - regnum);
  255.                 if( offset < 0xffff )
  256.                     return RWORD( offset );
  257.             }
  258.     }
  259.     return 0;
  260. }
  261.  
  262. /****************************************************************************
  263.  * Set a specific register
  264.  ****************************************************************************/
  265. void t11_set_reg(int regnum, unsigned val)
  266. {
  267.     switch( regnum )
  268.     {
  269.         case T11_PC: PC = val; /* change_pc not needed */ break;
  270.         case T11_SP: SP = val; break;
  271.         case T11_PSW: PSW = val; break;
  272.         case T11_R0: REGW(0) = val; break;
  273.         case T11_R1: REGW(1) = val; break;
  274.         case T11_R2: REGW(2) = val; break;
  275.         case T11_R3: REGW(3) = val; break;
  276.         case T11_R4: REGW(4) = val; break;
  277.         case T11_R5: REGW(5) = val; break;
  278.         case T11_IRQ0_STATE: t11_set_irq_line(T11_IRQ0,val); break;
  279.         case T11_IRQ1_STATE: t11_set_irq_line(T11_IRQ1,val); break;
  280.         case T11_IRQ2_STATE: t11_set_irq_line(T11_IRQ2,val); break;
  281.         case T11_IRQ3_STATE: t11_set_irq_line(T11_IRQ3,val); break;
  282.         case T11_BANK0: t11.bank[0] = &OP_RAM[val]; break;
  283.         case T11_BANK1: t11.bank[1] = &OP_RAM[val]; break;
  284.         case T11_BANK2: t11.bank[2] = &OP_RAM[val]; break;
  285.         case T11_BANK3: t11.bank[3] = &OP_RAM[val]; break;
  286.         case T11_BANK4: t11.bank[4] = &OP_RAM[val]; break;
  287.         case T11_BANK5: t11.bank[5] = &OP_RAM[val]; break;
  288.         case T11_BANK6: t11.bank[6] = &OP_RAM[val]; break;
  289.         case T11_BANK7: t11.bank[7] = &OP_RAM[val]; break;
  290.         default:
  291.             if( regnum < REG_SP_CONTENTS )
  292.             {
  293.                 unsigned offset = SPD + 2 * (REG_SP_CONTENTS - regnum);
  294.                 if( offset < 0xffff )
  295.                     WWORD( offset, val & 0xffff );
  296.             }
  297.     }
  298. }
  299.  
  300. /****************************************************************************
  301.  * Sets the banking
  302.  ****************************************************************************/
  303. void t11_SetBank(int offset, unsigned char *base)
  304. {
  305.     t11.bank[offset >> 13] = base;
  306. }
  307.  
  308.  
  309. void t11_reset(void *param)
  310. {
  311.     int i;
  312.  
  313.     memset(&t11, 0, sizeof(t11));
  314.     SP = 0x0400;
  315.     PC = 0x8000;
  316.     PSW = 0xe0;
  317.  
  318.     for (i = 0; i < 8; i++)
  319.         t11.bank[i] = &OP_RAM[i * 0x2000];
  320.     for (i = 0; i < 4; i++)
  321.         t11.irq_state[i] = CLEAR_LINE;
  322. }
  323.  
  324. void t11_exit(void)
  325. {
  326.     /* nothing to do */
  327. }
  328.  
  329. void t11_set_nmi_line(int state)
  330. {
  331.     /* T-11 has no dedicated NMI line */
  332. }
  333.  
  334. void t11_set_irq_line(int irqline, int state)
  335. {
  336.     t11.irq_state[irqline] = state;
  337.     if (state != CLEAR_LINE)
  338.         t11_check_irqs();
  339. }
  340.  
  341. void t11_set_irq_callback(int (*callback)(int irqline))
  342. {
  343.     t11.irq_callback = callback;
  344. }
  345.  
  346.  
  347. /* execute instructions on this CPU until icount expires */
  348. int t11_execute(int cycles)
  349. {
  350.     t11_ICount = cycles;
  351.     t11_ICount -= t11.interrupt_cycles;
  352.     t11.interrupt_cycles = 0;
  353.  
  354.     if (t11.wait_state)
  355.     {
  356.         t11_ICount = 0;
  357.         goto getout;
  358.     }
  359.  
  360. change_pc(0xffff);
  361.     do
  362.     {
  363.         t11.ppc = t11.reg[7];    /* copy PC to previous PC */
  364.  
  365.         CALL_MAME_DEBUG;
  366.  
  367.         t11.op = ROPCODE();
  368.         (*opcode_table[t11.op >> 3])();
  369.  
  370.         t11_ICount -= 22;
  371.  
  372.     } while (t11_ICount > 0);
  373.  
  374. getout:
  375.  
  376.     t11_ICount -= t11.interrupt_cycles;
  377.     t11.interrupt_cycles = 0;
  378.  
  379.     return cycles - t11_ICount;
  380. }
  381.  
  382. /****************************************************************************
  383.  * Return a formatted string for a register
  384.  ****************************************************************************/
  385. const char *t11_info( void *context, int regnum )
  386. {
  387.     static char buffer[16][47+1];
  388.     static int which = 0;
  389.     t11_Regs *r = context;
  390.  
  391.     which = ++which % 16;
  392.     buffer[which][0] = '\0';
  393.  
  394.     if( !context )
  395.         r = &t11;
  396.  
  397.     switch( regnum )
  398.     {
  399.         case CPU_INFO_REG+T11_PC: sprintf(buffer[which], "PC:%04X", r->reg[7].w.l); break;
  400.         case CPU_INFO_REG+T11_SP: sprintf(buffer[which], "SP:%04X", r->reg[6].w.l); break;
  401.         case CPU_INFO_REG+T11_PSW: sprintf(buffer[which], "PSW:%02X", r->psw.b.l); break;
  402.         case CPU_INFO_REG+T11_R0: sprintf(buffer[which], "R0:%04X", r->reg[0].w.l); break;
  403.         case CPU_INFO_REG+T11_R1: sprintf(buffer[which], "R1:%04X", r->reg[1].w.l); break;
  404.         case CPU_INFO_REG+T11_R2: sprintf(buffer[which], "R2:%04X", r->reg[2].w.l); break;
  405.         case CPU_INFO_REG+T11_R3: sprintf(buffer[which], "R3:%04X", r->reg[3].w.l); break;
  406.         case CPU_INFO_REG+T11_R4: sprintf(buffer[which], "R4:%04X", r->reg[4].w.l); break;
  407.         case CPU_INFO_REG+T11_R5: sprintf(buffer[which], "R5:%04X", r->reg[5].w.l); break;
  408.         case CPU_INFO_REG+T11_IRQ0_STATE: sprintf(buffer[which], "IRQ0:%X", r->irq_state[T11_IRQ0]); break;
  409.         case CPU_INFO_REG+T11_IRQ1_STATE: sprintf(buffer[which], "IRQ1:%X", r->irq_state[T11_IRQ1]); break;
  410.         case CPU_INFO_REG+T11_IRQ2_STATE: sprintf(buffer[which], "IRQ2:%X", r->irq_state[T11_IRQ2]); break;
  411.         case CPU_INFO_REG+T11_IRQ3_STATE: sprintf(buffer[which], "IRQ3:%X", r->irq_state[T11_IRQ3]); break;
  412.         case CPU_INFO_REG+T11_BANK0: sprintf(buffer[which], "B0:%06X", (unsigned)(r->bank[0] - OP_RAM)); break;
  413.         case CPU_INFO_REG+T11_BANK1: sprintf(buffer[which], "B1:%06X", (unsigned)(r->bank[1] - OP_RAM)); break;
  414.         case CPU_INFO_REG+T11_BANK2: sprintf(buffer[which], "B2:%06X", (unsigned)(r->bank[2] - OP_RAM)); break;
  415.         case CPU_INFO_REG+T11_BANK3: sprintf(buffer[which], "B3:%06X", (unsigned)(r->bank[3] - OP_RAM)); break;
  416.         case CPU_INFO_REG+T11_BANK4: sprintf(buffer[which], "B4:%06X", (unsigned)(r->bank[4] - OP_RAM)); break;
  417.         case CPU_INFO_REG+T11_BANK5: sprintf(buffer[which], "B5:%06X", (unsigned)(r->bank[5] - OP_RAM)); break;
  418.         case CPU_INFO_REG+T11_BANK6: sprintf(buffer[which], "B6:%06X", (unsigned)(r->bank[6] - OP_RAM)); break;
  419.         case CPU_INFO_REG+T11_BANK7: sprintf(buffer[which], "B7:%06X", (unsigned)(r->bank[7] - OP_RAM)); break;
  420.         case CPU_INFO_FLAGS:
  421.             sprintf(buffer[which], "%c%c%c%c%c%c%c%c",
  422.                 r->psw.b.l & 0x80 ? '?':'.',
  423.                 r->psw.b.l & 0x40 ? 'I':'.',
  424.                 r->psw.b.l & 0x20 ? 'I':'.',
  425.                 r->psw.b.l & 0x10 ? 'T':'.',
  426.                 r->psw.b.l & 0x08 ? 'N':'.',
  427.                 r->psw.b.l & 0x04 ? 'Z':'.',
  428.                 r->psw.b.l & 0x02 ? 'V':'.',
  429.                 r->psw.b.l & 0x01 ? 'C':'.');
  430.             break;
  431.         case CPU_INFO_NAME: return "T11";
  432.         case CPU_INFO_FAMILY: return "DEC T-11";
  433.         case CPU_INFO_VERSION: return "1.0";
  434.         case CPU_INFO_FILE: return __FILE__;
  435.         case CPU_INFO_CREDITS: return "Copyright (C) Aaron Giles 1998";
  436.         case CPU_INFO_REG_LAYOUT: return (const char*)t11_reg_layout;
  437.         case CPU_INFO_WIN_LAYOUT: return (const char*)t11_win_layout;
  438.     }
  439.     return buffer[which];
  440. }
  441.  
  442. unsigned t11_dasm(char *buffer, unsigned pc)
  443. {
  444. #ifdef MAME_DEBUG
  445.     return DasmT11(buffer,pc);
  446. #else
  447.     sprintf( buffer, "$%04X", cpu_readmem16lew_word(pc) );
  448.     return 2;
  449. #endif
  450. }
  451.  
  452.